Last updated on 2025-Feb-18 at 04:01 PM.
Data collected by Research Assistant Reann Post and Research Coordinator Lynn Murphy.
# load packages
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.0.4
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(here)
## here() starts at /Users/eadie/EadieTech/retinalogik-study
library(DT)
library(plotly)
##
## Attaching package: 'plotly'
##
## The following object is masked from 'package:ggplot2':
##
## last_plot
##
## The following object is masked from 'package:stats':
##
## filter
##
## The following object is masked from 'package:graphics':
##
## layout
library(viridis)
## Loading required package: viridisLite
library(svglite)
library(htmltools)
sessionInfo()
## R version 4.4.2 (2024-10-31)
## Platform: aarch64-apple-darwin20
## Running under: macOS Ventura 13.7.1
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.0
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## time zone: America/Halifax
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] htmltools_0.5.8.1 svglite_2.1.3 viridis_0.6.5 viridisLite_0.4.2
## [5] plotly_4.10.4 DT_0.33 here_1.0.1 lubridate_1.9.4
## [9] forcats_1.0.0 stringr_1.5.1 dplyr_1.1.4 purrr_1.0.4
## [13] readr_2.1.5 tidyr_1.3.1 tibble_3.2.1 ggplot2_3.5.1
## [17] tidyverse_2.0.0
##
## loaded via a namespace (and not attached):
## [1] sass_0.4.9 generics_0.1.3 stringi_1.8.4 hms_1.1.3
## [5] digest_0.6.37 magrittr_2.0.3 evaluate_1.0.3 grid_4.4.2
## [9] timechange_0.3.0 fastmap_1.2.0 rprojroot_2.0.4 jsonlite_1.8.9
## [13] gridExtra_2.3 httr_1.4.7 scales_1.3.0 lazyeval_0.2.2
## [17] jquerylib_0.1.4 cli_3.6.3 rlang_1.1.5 munsell_0.5.1
## [21] withr_3.0.2 cachem_1.1.0 yaml_2.3.10 tools_4.4.2
## [25] tzdb_0.4.0 colorspace_2.1-1 vctrs_0.6.5 R6_2.6.0
## [29] lifecycle_1.0.4 htmlwidgets_1.6.4 pkgconfig_2.0.3 pillar_1.10.1
## [33] bslib_0.9.0 gtable_0.3.6 glue_1.8.0 data.table_1.16.4
## [37] systemfonts_1.2.1 xfun_0.50 tidyselect_1.2.1 rstudioapi_0.17.1
## [41] knitr_1.49 rmarkdown_2.29 compiler_4.4.2
# default chunk options
knitr::opts_chunk$set(
comment = '>', cache = TRUE, collapse = TRUE, cache = FALSE, dev= c("png")
)
# load processed data
load(here("dBdat.Rda"))
We compared 24-2 Full Threshold visual field (VF) test results between Retinalogik and Humphrey Field Analyzer (HFA) in patients with early glaucoma and moderate to advanced glaucoma.
Eligible participants were identified among patients of Dr. Brennan Eadie at the Eadie Eye Centre. If deemed eligible for the study, subjects were recruited consecutively.
Each participant underwent five study visits. At each visit, they performed a VF test on both eyes using two devices. The order of device tested was randomized at the first (baseline) study visit.
The study adhered to the tenets of the Declaration of Helsinki for research involving human subjects and the protocol was approved by the Nova Scotia Health Research Ethics Board (#1030608). All participants gave their written informed consent before enrollment in the study.
All OS data will be transposed to OD format before analyses. Data from 11 participants (8 females, 2 males) aged 44 to 76 (M = 65.14, SD = 8.68) were included in the analysis.
library(ggplot2)
library(slickR)
# make sure coordinates are numeric, then flip OS to OD for plotting purposes
dBdat %<>%
mutate(x = as.numeric(x), y = as.numeric(y)) %>%
mutate(x = case_when(
eye == "L" & device == "hfa" ~ x*-1,
TRUE ~ as.numeric(x)))
dBdat %>%
mutate(dB = as.numeric(dB)) %>%
filter(device == "hfa") %>%
group_by(id, visit, eye) %>%
arrange(id, visit, eye) %>%
# Use the group_by %>% nest pattern to group data by id
nest() %>%
# Use map2 so the id can be used as the title
mutate(graphs = map2(data, id,
~ggplot(data = .x, aes(x, y, dB)) +
geom_raster(aes(x = x, y = y, fill = dB)) +
geom_text(aes(label = dB, x = x, y = y), size = 8) +
coord_fixed(ratio = 1) +
scale_fill_gradientn(colours = viridis(47), limits = c(-1, 46),
na.value="darkred") +
theme_bw() +
ggtitle(paste0("HFA ", id, " Visit ", visit, " Eye: ", eye))
)
) %>%
# pull is the pipe-able equivalent of .[['graphs']]
pull(graphs) %>%
# Return the svg of graphs
map(function(gr) svglite::xmlSVG(show(gr), standalone = TRUE)) ->
hfa_individual_graphs
dBdat %>%
mutate(dB = as.numeric(dB)) %>%
filter(device == "retinalogik") %>%
group_by(id, visit, eye) %>%
arrange(id, visit, eye) %>%
# Use the group_by %>% nest pattern to group data by id
nest() %>%
# Use map2 so the id can be used as the title
mutate(graphs = map2(data, id,
~ggplot(data = .x, aes(x, y, dB)) +
geom_raster(aes(x = x, y = y, fill = dB)) +
geom_text(aes(label = dB, x = x, y = y), size = 8) +
coord_fixed(ratio = 1) +
scale_fill_gradientn(colours = viridis(47), limits = c(-1, 46),
na.value="darkred") +
theme_bw() +
ggtitle(paste0("Retinalogik ", id, " Visit ", visit, " Eye: ", eye))
)
) %>%
# pull is the pipe-able equivalent of .[['graphs']]
pull(graphs) %>%
# Return the svg of graphs
map(function(gr) svglite::xmlSVG(show(gr), standalone = TRUE)) ->
rt_individual_graphs
# carousels
hfa_plots <- slickR(hfa_individual_graphs, height = 350, width = "95%", padding = 0) +
settings(slidesToShow = 2, slidesToScroll = 2)
rt_plots <- slickR(rt_individual_graphs, height = 350, width = "95%", padding = 0) +
settings(slidesToShow = 2, slidesToScroll = 2)
rt_plots %synch% hfa_plots
Instrument output mean deviation and pattern standard deviation measurements were strongly correlated between devices. The intraclass correlation co-efficient was similar to the Pearson r for mean deviation (0.87 vs. 0.86) but was lower than the Pearson r for pattern standard deviation (0.94 vs. 0.82).
library(psych)
>
> Attaching package: 'psych'
> The following objects are masked from 'package:ggplot2':
>
> %+%, alpha
hfa <- dBdat %>%
# filter(id == "RL01" ) %>%
filter(device=="hfa") %>%
distinct(id, visit, md)
retinalogik <- dBdat %>%
filter(id != "RL04") %>%
filter(device=="retinalogik") %>%
distinct(id, visit, md)
tmp <- dBdat %>%
# filter(id == "RL01" ) %>%
# filter(device=="hfa") %>%
distinct(id, visit, device, eye, md) %>%
arrange(id, visit, eye)
md <- tibble(hfa=hfa$md, rl=retinalogik$md)
ICC(md,missing=TRUE,alpha=.05,lmer=TRUE,check.keys=FALSE)
> boundary (singular) fit: see help('isSingular')
> Call: ICC(x = md, missing = TRUE, alpha = 0.05, lmer = TRUE, check.keys = FALSE)
>
> Intraclass correlation coefficients
> type ICC F df1 df2 p lower bound upper bound
> Single_raters_absolute ICC1 0.15 1.3 48 49 0.15 -0.14 0.41
> Single_random_raters ICC2 0.15 1.3 48 48 0.15 -0.14 0.41
> Single_fixed_raters ICC3 0.15 1.3 48 48 0.15 -0.14 0.41
> Average_raters_absolute ICC1k 0.26 1.3 48 49 0.15 -0.31 0.58
> Average_random_raters ICC2k 0.26 1.3 48 48 0.15 -0.32 0.58
> Average_fixed_raters ICC3k 0.26 1.3 48 48 0.15 -0.32 0.58
>
> Number of subjects = 49 Number of Judges = 2
> See the help file for a discussion of the other 4 McGraw and Wong estimates,
For those interested in the cleaned up data.
dBdat %>%
select(id, age, device, eye, x, y, dB) %>%
datatable(options = list(
order = list(1, 'asc')
))
Report by Vivian Eng